home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / UTIL / MEMORY / OLD / MEM208SRC / !Memphis / c / memfiler < prev    next >
Text File  |  1993-09-09  |  26KB  |  959 lines

  1. /*
  2.  * memfiler.c
  3.  * Part of the !Memphis distribution
  4.  * (c) bdb/nas, 1991-3
  5.  */
  6.  
  7. /* Developed by NAS from:
  8.  * FSLib c.filer 3.1 93/03/09 20:00:45 brian Exp
  9.  */
  10.  
  11. #define FS "Mem"
  12. #define DISK "Sprites"
  13. static char quitmsg[]="\0\0\0\0The data in the system sprite area will be lost if you closedown MemFS. Are you sure that you want to proceed?";
  14. static char validstr[]="Smemfs";
  15. static int sprx=43,spry=11;
  16. static char RootName[]= FS"::"DISK".$";
  17. #define RootName1 RootName
  18. static int FilingSystemNumber=91; /* Acorn-allocated FS number */
  19. /* #define KILLCMD1 "SNew" */
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include "kernel.h"
  25. #include "swis.h"
  26. #include "ModuleWrap.h"
  27. #include "util.h"
  28. #include "cstart.h"
  29. #include "wimp.h"
  30.  
  31. #define RUNNABLE        /* to enable direct running */
  32. #define TASK    ('K'<<24|'S'<<16|'A'<<8|'T')
  33.  
  34. /* FilerAction SWI calls */
  35. #define FilerAction_SendSelectedDirectory       0x40f80
  36. #define FilerAction_SendSelectedFile            0x40f81
  37. #define FilerAction_SendStartOperation          0x40f82
  38. #define wimp_MFilerSelectionDirectory           0x403
  39. #define wimp_MFilerAddSelection                 0x404
  40. #define wimp_MFilerAction                       0x405
  41.  
  42. int             taskhandle;
  43. int             taskstack;
  44. static int      wind_info = -1;
  45. static int      wind_create = -1;
  46. static char     workspace[512];
  47. static BOOL     protection = FALSE;
  48.  
  49. static int      filertaskhandle;
  50. static char FilerName[]= FS"FSFiler";
  51. static BOOL     dragging = FALSE;
  52.  
  53. /* Define TRACESERVICE in order to output trace of service calls */
  54. /* #define TRACESERVICE */
  55.  
  56. static void removetask(void)
  57. {
  58.   _kernel_swi_regs r;
  59.  
  60.   r.r[0]=taskhandle;
  61.   r.r[1]=TASK;
  62.   taskhandle=0;
  63.   if (r.r[0] && r.r[0]!=-1)
  64.     _kernel_swi( XOS_Bit | Wimp_CloseDown , &r, &r );
  65.   if (taskstack)
  66.     free((char *)taskstack);
  67.   taskstack=0;
  68. }
  69.  
  70. /* RISC_OSLib wimp_starttask doesn't return task handle */
  71. static int wimp_newtask(char *clicmd)
  72. {
  73.   _kernel_swi_regs r;
  74.  
  75.   r.r[0]=(int) clicmd;
  76.   _kernel_swi( XOS_Bit | Wimp_StartTask , &r, &r );
  77.   return(r.r[0]);
  78. }
  79.  
  80. /*
  81.  * ResourceFS handling routines
  82.  */
  83.  
  84. #define Service_ResourceStarting        0x60
  85.  
  86. extern int templates_data[];
  87. extern void service_resourcefsstarting(int none, int reason, int addr, int wkptr);
  88. extern void resource_registerfiles(void);
  89. extern void resource_deregisterfiles(void);
  90. extern void protect_code(void);
  91.  
  92. static int finalise_privateword;
  93.  
  94. /*
  95.  * This is the finalisation code
  96.  */
  97. static void fs_finalise(void)
  98. {
  99.   _kernel_swi_regs r;
  100.   resource_deregisterfiles();
  101.   if (protection)
  102.   {
  103.     r.r[0] = 0x1F;
  104.     r.r[1] = (int) &protect_code;
  105.     r.r[2] = finalise_privateword;
  106.     protection = FALSE;
  107.     _kernel_swi( XOS_Bit | OS_Release, &r, &r );
  108.   }
  109.   removetask();
  110. }
  111.  
  112. /*
  113.  * This is the initialisation code
  114.  */
  115. _kernel_oserror *fs_initialise(char *cmd_tail, int podule_base, void *private_word)
  116. {
  117.   _kernel_oserror *err=NULL;
  118.  
  119.   private_word=private_word;
  120.   finalise_privateword = (int) private_word;
  121.   /*
  122.    * These keep the compiler quiet.
  123.    */
  124.   cmd_tail = cmd_tail;
  125.   podule_base = podule_base;
  126.  
  127.   /*
  128.    * Must record fact filer task is not running
  129.    */
  130.   taskhandle = 0;
  131.   taskstack = 0 ; /* and that its stack is not yet allocated */
  132.  
  133.   resource_registerfiles();
  134.   atexit( fs_finalise );
  135.  
  136.   return err;
  137. }
  138.  
  139. /*
  140.  * Service call handler
  141.  */
  142.  
  143. #ifdef TRACESERVICE
  144. static struct {int svc; char *name;} svcs[] =
  145. {
  146.   {0x00,"Serviced"},
  147.   {0x04,"UKCommand"},
  148.   {0x06,"Error"},
  149.   {0x07,"UKByte"},
  150.   {0x08,"UKWord"},
  151.   {0x09,"Help"},
  152.   {0x0b,"ReleaseFIQ"},
  153.   {0x0c,"ClaimFIQ"},
  154.   {0x11,"Memory"},
  155.   {0x12,"StartUpFS"},
  156.   {0x27,"Reset"},
  157.   {0x28,"UKConfig"},
  158.   {0x29,"UKStatus"},
  159.   {0x2a,"NewApplication"},
  160.   {0x40,"FSRedclare"},
  161.   {0x41,"Print"},
  162.   {0x42,"LookupFileType"},
  163.   {0x43,"International"},
  164.   {0x44,"Keyhandler"},
  165.   {0x45,"PreReset"},
  166.   {0x46,"ModeChange"},
  167.   {0x47,"ClaimFIQinBackground"},
  168.   {0x48,"ReAllocatePorts"},
  169.   {0x49,"StartWimp"},
  170.   {0x4a,"StartedWimp"},
  171.   {0x4b,"StartFiler"},
  172.   {0x4c,"StartedFiler"},
  173.   {0x4d,"PreModeChange"},
  174.   {0x4e,"MemoryMoved"},
  175.   {0x4f,"FilerDying"},
  176.   {0x50,"ModeExtension"},
  177.   {0x51,"ModeTranslation"},
  178.   {0x52,"MouseTrap"},
  179.   {0x53,"WimpCloseDown"},
  180.   {0x54,"Sound"},
  181.   {0x55,"NetFS"},
  182.   {0x56,"EconetDying"},
  183.   {0x57,"WimpReportError"},
  184.   {0x60,"ResourceFSStarting"},
  185.   {-1,"Something else"}
  186. };
  187. #endif
  188.  
  189. void fs_service(int service_number, _kernel_swi_regs *r, void *private_word)
  190. {
  191. #ifdef TRACESERVICE
  192.   int i;
  193.  
  194.   for (i=0; svcs[i].svc>=0; i++) if (svcs[i].svc==service_number) break;
  195.   printf("Service_%s (%#x)%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\r\n",svcs[i].name,
  196.         service_number,*r);
  197. #endif
  198.   private_word=private_word;
  199.   switch( service_number )
  200.   {
  201.     case Service_StartFiler:
  202.       if (!taskhandle)
  203.       {
  204.         filertaskhandle=r->r[0];
  205.         taskhandle=-1; /* attempting start flag */
  206.         r->r[0]=(int)("Desktop_"FS"FSFiler");
  207.         r->r[1]=0;
  208.       }
  209.       break;
  210.     case Service_StartedFiler:
  211.       if (taskhandle==-1)
  212.         taskhandle=0;
  213.       break;
  214.     case Service_Reset:
  215.       taskhandle=0;
  216.       protection=FALSE;
  217.       break;
  218.     case Service_FilerDying:
  219.       removetask();
  220.       break;
  221.     case Service_ResourceStarting:
  222.       service_resourcefsstarting(r->r[0], r->r[1], r->r[2], r->r[3]);
  223.       break;
  224.     /*
  225.      * Handle other service calls here
  226.      */
  227.   }
  228. }
  229.  
  230. /*
  231.  * command processor
  232.  */
  233. _kernel_oserror *fs_command(char *arg_string, int argc, int cmd_no, void *private_word)
  234. {
  235.   _kernel_swi_regs r;
  236. #define My_Command_Parameter_Buffer_Len 256
  237.   static char my_command_parameter_buffer[ My_Command_Parameter_Buffer_Len ];
  238.   char *temptr = my_command_parameter_buffer;
  239.  
  240.   argc = argc;
  241.   private_word = private_word;
  242.  
  243.   /*
  244.    * Change the control character terminator to a nul terminator
  245.    */
  246.   for ( ; temptr - my_command_parameter_buffer < My_Command_Parameter_Buffer_Len && *arg_string >= ' ' ; )
  247.   {
  248.     *temptr++ = *arg_string++;
  249.   }
  250.  
  251.   *temptr = '\0';
  252.  
  253.   arg_string = my_command_parameter_buffer;
  254.  
  255.   /*
  256.    * Switch between the commands
  257.    */
  258.   switch ( cmd_no )
  259.   {
  260.     case 0: /*      *Desktop_FSnameFSFiler */
  261.       if (taskhandle!=-1)
  262.       {
  263. #ifndef RUNNABLE
  264.         printf("Use *Desktop to start %s\n",FilerName);
  265.         return NULL;
  266. #else
  267.         removetask();
  268.         taskhandle=-1;
  269. #endif
  270.       }
  271.       r.r[0] = OSModule_Enter;
  272.       r.r[1] = (int)FilerName;
  273.       r.r[2] = (int)arg_string;
  274.       return _kernel_swi( XOS_Bit | OS_Module, &r, &r );
  275.     case 1: /*      *MemProtect */
  276.       if (protection) return NULL;
  277.       r.r[0] = 0x1F;
  278.       r.r[1] = (int) &protect_code;
  279.       r.r[2] = (int)private_word;
  280.       protection = TRUE;
  281.       return _kernel_swi( XOS_Bit | OS_Claim, &r, &r );
  282.     case 2: /*      *MemNormal*/
  283.       if (!protection) return NULL;
  284.       r.r[0] = 0x1F;
  285.       r.r[1] = (int) &protect_code;
  286.       r.r[2] = (int)private_word;
  287.       protection = FALSE;
  288.       return _kernel_swi( XOS_Bit | OS_Release, &r, &r );
  289.     default:
  290.       return NULL;
  291.   }
  292. }
  293.  
  294. int filertask(char *cmdtail);
  295.  
  296. #define MENUDEPTH 4
  297.  
  298. static struct
  299. {
  300.   wimp_menuhdr hdr;
  301.   wimp_menuitem item[MENUDEPTH];
  302. } mymenu=
  303. { { "Menutitle", 7, 2, 7, 0, 128, 44, 0 },
  304.   {
  305.     {   0,
  306.         (wimp_menuptr) -1,
  307.         wimp_ITEXT | wimp_IBTYPE*wimp_BNOTIFY | wimp_IFORECOL*7 | wimp_IBACKCOL*0,
  308.         "Info"
  309.     },
  310.     {   0,
  311.         (wimp_menuptr) -1,
  312.         wimp_ITEXT | wimp_IBTYPE*wimp_BNOTIFY | wimp_IFORECOL*7 | wimp_IBACKCOL*0,
  313.         "Create"
  314.     },
  315.     {   0,
  316.         (wimp_menuptr) -1,
  317.         wimp_ITEXT | wimp_IBTYPE*wimp_BNOTIFY | wimp_IFORECOL*7 | wimp_IBACKCOL*0,
  318.         "Free"
  319.     },
  320.     {
  321.         wimp_MLAST,
  322.         (wimp_menuptr) -1,
  323.         wimp_ITEXT | wimp_IBTYPE*wimp_BNOTIFY | wimp_IFORECOL*7 | wimp_IBACKCOL*0,
  324.         "Quit"
  325.     }
  326.   }
  327. };
  328.  
  329. /*
  330.  * DragASprite routines
  331.  */
  332.                                
  333. #define DragASprite_Start       0x42400
  334. #define DragASprite_Stop        0x42401
  335.  
  336. static os_error * drag_spritestart(int flags, void *area, char *name,
  337.                         wimp_box b1, wimp_box b2)
  338. { os_regset r;
  339.   os_error *e;
  340.  
  341.   r.r[0] = flags;
  342.   r.r[1] = (int) area;
  343.   r.r[2] = (int) name;
  344.   r.r[3] = (int) &b1;
  345.   r.r[4] = (int) &b2;
  346.   e = os_swix(DragASprite_Start, &r);
  347.   return(e);
  348. }
  349.  
  350. static os_error * drag_spritestop(void)
  351. { os_regset r;
  352.   os_error *e;
  353.  
  354.   e = os_swix(DragASprite_Stop, &r);
  355.   return(e);
  356. }
  357.  
  358. typedef struct {          /* icon description structure */
  359.   wimp_w w;
  360.   wimp_i i;
  361.   wimp_box box;           /* bounding box - relative to
  362.                            * window origin (work area top left) */
  363.   wimp_iconflags flags;   /* word of flag bits defined above */
  364.   wimp_icondata data;     /* union of bits & bobs as above */
  365. } wimp_iconstr;
  366.  
  367. /*
  368.  * Performs a simple xfersend() type operation upon dragging file icon
  369.  */
  370. static void ourxfersend(void)
  371. {
  372.   wimp_dragstr dr;
  373.   wimp_wstate wstate;
  374.   wimp_iconstr icon;
  375.   wimp_w w = wind_create;
  376.   wimp_mousestr mouse_str;
  377.   int x_limit = 32768, y_limit = 32768;
  378.   int screen_x0, screen_y0, mouse_x, mouse_y, x0, y0, x1, y1;
  379.   _kernel_swi_regs r;
  380.   os_error *err;
  381.   int x, y;
  382.  
  383.   /* Wimp_GetPointerInfo */
  384.   r.r[1] = (int) &mouse_str;
  385.   err=(os_error *)_kernel_swi(Wimp_GetPointerInfo, &r, &r );
  386.   mouse_x = mouse_str.x;
  387.   mouse_y = mouse_str.y;
  388.  
  389.   /* Wimp_GetWindState */
  390.   r.r[1] = (int) &wstate;
  391.   wstate.o.w = w;
  392.   err=(os_error *)_kernel_swi(Wimp_GetWindowState, &r, &r );
  393.   screen_x0 = wstate.o.box.x0 - wstate.o.x;
  394.   screen_y0 = wstate.o.box.y1 - wstate.o.y;
  395.  
  396.   /* Wimp_GetIconInfo */
  397.   r.r[1] = (int) &icon;
  398.   icon.w = w;
  399.   icon.i = 3;
  400.   err=(os_error *)_kernel_swi(Wimp_GetIconState, &r, &r );
  401.   x0 = screen_x0 + icon.box.x0;
  402.   y0 = screen_y0 + icon.box.y0;
  403.   x1 = screen_x0 + icon.box.x1;
  404.   y1 = screen_y0 + icon.box.y1;
  405.  
  406.   /* RISC OS 3.00 or later, we have DragASprite */
  407.   x = 0x1C; y = 0;
  408.   os_byte(161, &x, &y);
  409.   if ((y & 2) == 2)
  410.   { char *name = "file_3f1";
  411.     wimp_box b1, b2;
  412.  
  413.     /* DragASprite bit set, go for it ! */
  414.     b1.x0 = x0; b1.x1 = x1;
  415.     b1.y0 = y0; b1.y1 = y1;
  416.     drag_spritestart(197, (void *) 1, name, b1, b2);
  417.     dragging = TRUE;
  418.   }
  419.   else
  420.   {
  421.     /* Set up drag */
  422.     dr.window    = w; /*not relevant*/
  423.     dr.type      = wimp_USER_FIXED;
  424.     dr.box.x0    = x0;
  425.     dr.box.y0    = y0;
  426.     dr.box.x1    = x1;
  427.     dr.box.y1    = y1;
  428.     dr.parent.x0 = x0 - mouse_x; /*Expanded parent by box overlap*/
  429.     dr.parent.y0 = y0 - mouse_y;
  430.     dr.parent.x1 = x1 - mouse_x + x_limit;
  431.     dr.parent.y1 = y1 - mouse_y + y_limit;
  432.     r.r[1] = (int) &dr;
  433.     err=(os_error *)_kernel_swi(Wimp_DragBox, &r, &r );
  434.     dragging = FALSE;
  435.   }
  436. }
  437.  
  438. /* --- Read from an indirected text icon --- */
  439. static void wind_getstring(wimp_w window, wimp_i icon, char *text)
  440. { wimp_iconstr res;
  441.   _kernel_swi_regs r;
  442.  
  443.   /* Get the current state of specified icon */
  444.   r.r[1] = (int) &res;
  445.   res.w = window;
  446.   res.i = icon;
  447.   _kernel_swi(Wimp_GetIconState, &r, &r );
  448.  
  449.   /* Read from indirected text buffer */
  450.   strcpy(text, res.data.indirecttext.buffer);
  451. }
  452.  
  453. /* --- Update an indirected text icon --- */
  454. static void wind_setstring(wimp_w window, wimp_i icon, char *text)
  455. { wimp_iconstr     res;
  456.   _kernel_swi_regs r;
  457.  
  458.   /* Get the current state of specified icon */
  459.   r.r[1] = (int) &res;
  460.   res.w = window;
  461.   res.i = icon;
  462.   _kernel_swi(Wimp_GetIconState, &r, &r );
  463.  
  464.   /* Write to indirected text buffer */
  465.   strcpy(res.data.indirecttext.buffer, text);
  466. }
  467.  
  468. /*
  469.  * Sends out an appropriate DATASAVE message for creating a memdisc
  470.  */
  471. static void creatememdisc()
  472. {
  473.   wimp_mousestr mousestr;
  474.   wimp_msgstr msg;
  475.   _kernel_swi_regs r;
  476.   os_error *err;
  477.   int i, tail;
  478.   char name[256];
  479.  
  480.   /* Wimp_GetPointerInfo */
  481.   r.r[1] = (int) &mousestr;
  482.   err=(os_error *)_kernel_swi(Wimp_GetPointerInfo, &r, &r );
  483.  
  484.   if ((mousestr.w < 0) || (mousestr.w == wind_create)) return;  /* do nothing */
  485.   msg.hdr.size = sizeof(wimp_msghdr) + sizeof(wimp_msgdatasave);
  486.   msg.hdr.task = mousestr.w;
  487.   msg.hdr.your_ref = 0;
  488.   msg.hdr.action = wimp_MDATASAVE;
  489.   msg.data.datasave.w = mousestr.w;
  490.   msg.data.datasave.i = mousestr.i;
  491.   msg.data.datasave.x = mousestr.x;
  492.   msg.data.datasave.y = mousestr.y;
  493.   msg.data.datasave.type = 0x3F1;
  494.   msg.data.datasave.estsize = 0;
  495.  
  496.   wind_getstring(wind_create, 2, (char *) &name);
  497.   tail = strlen(name); /* point at the zero */
  498.   while (tail > 0 && name[tail-1] != '.' && name[tail-1] != ':')
  499.     tail--;
  500.  
  501.   for (i = 0; i <= 10; i++) msg.data.datasave.leaf[i] = name[tail++];
  502.   msg.data.datasave.leaf[11] = '\0' ;     /* force termination */
  503.  
  504.   err=wimp_sendwmessage(wimp_ESEND,&msg,mousestr.w, mousestr.i);
  505.   err=wimp_create_menu((wimp_menustr *) -1,0,0);
  506. }
  507.  
  508. /*
  509.  * Checks dest path for missing "." before calling creatememdisc()
  510.  */
  511. static void precreatememdisc()
  512. {
  513.   char filename[256];
  514.   BOOL dot = FALSE;
  515.   os_error err;
  516.   int i = 0;
  517.   _kernel_swi_regs r;
  518.  
  519.   /* Check for name with no "." in it, and complain if so. */
  520.   wind_getstring(wind_create, 2, (char *) &filename);
  521.   while ((! dot) && filename[i] != 0) dot = (filename[i++] == '.');
  522.   if (!dot)
  523.   {
  524.     err.errnum = 0;
  525.     strcpy(err.errmess, "To save, drag the icon to a directory viewer.");
  526.     wimp_reporterror(&err,0, FilerName);
  527.   }
  528.   else
  529.   {
  530.     char buf[256];
  531.     sprintf(buf, "ColonSemi %s\n", filename);
  532.     /* For some annoying reason (stack, workspace??) use of system() was causing
  533.      * fatal crashes at program exit
  534.      */
  535.     r.r[0] = (int) buf;
  536.     _kernel_swi(OS_CLI, &r, &r );
  537.     strcpy(buf, "Do Filer_OpenDir Mem#|<ColonSemi>:$");
  538.     r.r[0] = (int) buf;
  539.     _kernel_swi(OS_CLI, &r, &r );
  540.     wind_setstring(wind_create, 2, filename);
  541.     wimp_create_menu((wimp_menustr *) -1,0,0);
  542.   }
  543. }
  544.  
  545. /*
  546.  * Delete any mfs* sprites in system sprite area
  547.  */
  548. static void wipespritearea(void)
  549. {
  550.   _kernel_swi_regs r;
  551.   os_error *err;
  552.   int nsprites, loop;
  553.   char name[13];
  554.  
  555.   r.r[0] = 8;
  556.   err=(os_error *)_kernel_swi(OS_SpriteOp, &r, &r );
  557.   nsprites = r.r[3];
  558.   if ((err) || (nsprites < 1) || (r.r[2] < 1)) return;
  559.  
  560.   _kernel_swi(Hourglass_On, &r, &r );
  561.   loop = nsprites;
  562.   do
  563.   {
  564.      r.r[0] = 13;
  565.      r.r[2] = (int) &name;
  566.      r.r[3] = 12;
  567.      r.r[4] = loop;
  568.      _kernel_swi(OS_SpriteOp, &r, &r );
  569.      if ((name[0] = 'm') && (name[1] = 'f') && (name[2] = 's'))   
  570.      {
  571.        r.r[0] = 25;
  572.        r.r[2] = (int) &name;
  573.        _kernel_swi(OS_SpriteOp, &r, &r );
  574.      }
  575.   } while ((loop--)>1);
  576.  
  577.   _kernel_swi(Hourglass_Off, &r, &r );
  578. }
  579.  
  580. /*
  581.  * Template open/load/close code 
  582.  */
  583. static os_error *template(int osver)
  584. {
  585.   _kernel_swi_regs r;
  586.   os_error *err;
  587.   char path[] = "Resources:$.Resources.Memphis.Template3D";
  588.   char name[12];
  589.   char templates[512];
  590.   int x, y;
  591.  
  592.   /* '3D-look' bit */
  593.   x = 140; y = 0;
  594.   os_byte(161, &x, &y);
  595.   if (((y & 1) == 0) || (osver < 300))
  596.   {
  597.     strcpy(path, "Resources:$.Resources.Memphis.Templates");
  598.   }
  599.  
  600.   r.r[1]=(int) path;
  601.   err=(os_error *)_kernel_swi(Wimp_OpenTemplate, &r, &r );
  602.   if (err) return(err);
  603.   strcpy(name, "progInfo");
  604.   r.r[1] = (int) templates;
  605.   r.r[2] = (int) workspace;
  606.   r.r[3] = (int) workspace + sizeof(workspace);
  607.   r.r[4] = -1;
  608.   r.r[5] = (int) name;
  609.   r.r[6] = 0;
  610.   err=(os_error *)_kernel_swi(Wimp_LoadTemplate, &r, &r );
  611.   if (err) return(err);
  612.   err=(os_error *)_kernel_swi(Wimp_CreateWindow, &r, &r );
  613.   if (err) return(err);
  614.   wind_info = r.r[0];
  615.   strcpy(name, "xfer_make");
  616.   r.r[6] = 0;
  617.   err=(os_error *)_kernel_swi(Wimp_LoadTemplate, &r, &r );
  618.   if (err) return(err);
  619.   err=(os_error *)_kernel_swi(Wimp_CreateWindow, &r, &r );
  620.   if (err) return(err);
  621.   wind_create = r.r[0];
  622.   err=(os_error *)_kernel_swi(Wimp_CloseTemplate, &r, &r );
  623.   if (err) return(err);
  624.  
  625.   return(NULL);
  626. }
  627.  
  628. /* --- RISC OS print with file handle rather than stream --- */
  629. static void rofprint(int fh, char *text)
  630. { _kernel_osgbpb_block b;
  631.  
  632.   b.dataptr = text;
  633.   b.nbytes = strlen( text );
  634.   _kernel_osgbpb( 2, fh, &b );
  635. }
  636.  
  637. int filertask(char *cmdtail)
  638. {
  639.   _kernel_swi_regs r;
  640.   os_error *err;
  641.   wimp_icreate wi;
  642.   wimp_i icon;
  643.   wimp_eventstr ev;
  644.   wimp_mousestr m;
  645.   int wimpversion;
  646.   int maydataload=0;
  647.  
  648. #ifndef RUNNABLE
  649.   if (taskhandle!=-1)
  650.     return 0;
  651. #endif
  652.   cmdtail=cmdtail; /* Use it to scare off warnings */
  653.   r.r[0]=310;
  654.   r.r[1]=TASK;
  655.   r.r[2]=(int)FilerName;
  656.   r.r[3]=-1;
  657.   err=(os_error *)_kernel_swi( Wimp_Initialise, &r, &r );
  658. /*  err=wimp_taskinit( FilerName, (wimp_t*)&taskhandle ); */
  659.   if (err)
  660.     goto error;
  661.   wimpversion=r.r[0];
  662.   taskhandle=r.r[1];
  663.   if (wimpversion>200)
  664.     wi.w=-6, r.r[0]=0x3F000000;
  665.   else
  666.     wi.w=-2;
  667.   wi.i.box.x0=0;
  668.   wi.i.box.y0=-16; /* base of text, 32 high */
  669.   wi.i.box.x1=2*sprx;
  670.   wi.i.box.y1=-16+32+4+4*spry;
  671.   wi.i.flags=wimp_ITEXT |
  672.              wimp_ISPRITE |
  673.              wimp_IHCENTRE |
  674.              wimp_INDIRECT |
  675.              wimp_IBTYPE*wimp_BCLICKDEBOUNCE |
  676.              wimp_IFORECOL*7 |
  677.              wimp_IBACKCOL*1 ;
  678.   wi.i.data.indirecttext.buffer=FS;
  679.   wi.i.data.indirecttext.validstring=validstr;
  680.   wi.i.data.indirecttext.bufflen=3;
  681.   r.r[1]=(int)&wi;
  682.   err=(os_error *)_kernel_swi( Wimp_CreateIcon, &r, &r );
  683.   icon=r.r[0];
  684.   /* err=wimp_create_icon(&wi,&icon); */
  685.   if (err)
  686.     goto error;
  687.   err=(os_error *)template(wimpversion);
  688.   if (err)
  689.     goto error;
  690.  
  691.   for (;;)
  692.   {
  693.     maydataload = 0;
  694. pol:err=wimp_poll(wimp_EMNULL,&ev);
  695.     if (err)
  696.       goto error;
  697.     switch (ev.e)
  698.     {
  699.       case wimp_EOPEN:
  700.         err=wimp_open_wind(&ev.data.o);
  701.         continue;
  702.  
  703.       case wimp_EBUT:
  704.         if (ev.data.but.m.i == icon)
  705.         {
  706.           switch (ev.data.but.m.bbits)
  707.           {
  708.             case wimp_BLEFT:
  709.             case wimp_BRIGHT:
  710.               ev.data.msg.hdr.size=sizeof(wimp_msghdr)+sizeof(int)*2+
  711.                   (strlen(RootName)&~3)+4;
  712.               ev.data.msg.hdr.your_ref=0;
  713.               ev.data.msg.hdr.action=wimp_FilerOpenDir;
  714.               ev.data.msg.data.words[0]=FilingSystemNumber;
  715.               ev.data.msg.data.words[1]=0;
  716.               strcpy((char *)&ev.data.msg.data.words[2],
  717.                   ev.data.but.m.bbits==wimp_BLEFT?RootName:RootName1 );
  718.               err=wimp_sendmessage(wimp_ESEND,&ev.data.msg,(wimp_t)filertaskhandle);
  719.               if (err)
  720.                 goto error;
  721.               continue;
  722.             case wimp_BMID:
  723.               strcpy(mymenu.hdr.title,FS"FS");
  724.               mymenu.item[0].submenu = (wimp_menuptr) wind_info;
  725.               mymenu.item[1].submenu = (wimp_menuptr) wind_create;
  726.               err=wimp_create_menu((wimp_menustr *)&mymenu,ev.data.but.m.x-64,
  727.                   96+MENUDEPTH*44);
  728.               if (err)
  729.                 goto error;
  730.               continue;
  731.             default:
  732.               continue;
  733.           }
  734.         }
  735.         if ((ev.data.but.m.i == 0) && (ev.data.but.m.w == wind_create))
  736.         {
  737.           precreatememdisc();
  738.         }
  739.         if ((ev.data.but.m.i == 3) && (ev.data.but.m.w == wind_create))
  740.         {
  741.           switch (ev.data.but.m.bbits)
  742.           {
  743.             case wimp_BDRAGLEFT:
  744.             case wimp_BDRAGRIGHT:
  745.               ourxfersend();
  746.               continue;
  747.             default:
  748.              continue;
  749.           }
  750.         } 
  751.         continue;
  752.       break;
  753.  
  754.     case wimp_EMENU:
  755.       switch (ev.data.menu[0])
  756.       {
  757.         case 0: /* Info */
  758.           break;
  759.         case 1: /* Create */
  760.           break;
  761.         case 2: /* Free */
  762.           if (_kernel_oscli("ShowFree -fs "FS" "DISK)==_kernel_ERROR)
  763.                 _kernel_oscli("WimpTask "FS":Free "DISK);
  764.           break;
  765.         case 3: /* Quit */
  766.           r.r[0]=17;
  767.           r.r[1]=(int)&RootName;
  768.           if (!_kernel_swi( OS_File, &r, &r ) && r.r[4] )
  769.           {
  770.             r.r[0]=(int)&quitmsg;
  771.             r.r[1]=3+(1<<4);
  772.             r.r[2]=(int)FilerName;
  773.             err=(os_error *)_kernel_swi( Wimp_ReportError, &r, &r );
  774.             if (r.r[1]!=1)
  775.               continue;
  776.           }
  777.           r.r[1] = 0x7D;
  778.           r.r[2] = (int) FS"::"DISK"";
  779.           _kernel_swi( OS_ServiceCall, &r, &r );
  780.           _kernel_oscli("RMKill "FS"FS");
  781.  #ifdef KILLCMD1
  782.           _kernel_oscli(KILLCMD1);
  783. #else
  784.           wipespritearea();
  785. #endif
  786.           r.r[0]=3;
  787.           r.r[1]=-4<<20;
  788.           _kernel_swi( OS_ChangeDynamicArea, &r, &r );
  789.           r.r[0]=0;
  790.           r.r[3]=(int)&FilerName;
  791.           _kernel_swi( OS_ExitAndDie, &r, &r );    
  792.       }
  793.       r.r[1]=(int)&m;
  794.       _kernel_swi(Wimp_GetPointerInfo, &r, &r );
  795.       if (m.bbits == wimp_BRIGHT)
  796.       {
  797.         err=wimp_create_menu((wimp_menustr *)&mymenu,m.x, m.y);
  798.         if (err) goto error;
  799.       }
  800.       continue;
  801.  
  802.     case wimp_EKEY:
  803.       if ((ev.data.key.c.w == wind_create) && (ev.data.key.chcode == 13))
  804.       {
  805.         precreatememdisc();
  806.       } else
  807.       {
  808.         r.r[0] = ev.data.key.chcode;
  809.         _kernel_swi( Wimp_ProcessKey, &r, &r );
  810.       }
  811.       continue;
  812.  
  813.     case wimp_EUSERDRAG:
  814.       if (dragging)
  815.       {
  816.         /* Clean up DragASprite workspace */
  817.         drag_spritestop();
  818.         dragging = FALSE;
  819.       }
  820.       creatememdisc();
  821.       continue;
  822.  
  823.     case wimp_ESEND:
  824.     case wimp_ESENDWANTACK:
  825.       switch (ev.data.msg.hdr.action)
  826.       {
  827.         char buf[256];
  828.         case wimp_MCLOSEDOWN:
  829.           break;
  830.         case wimp_MDATASAVE:
  831.           strcpy(buf,RootName);
  832.           strcat(buf,".");
  833.           strcat(buf,ev.data.msg.data.datasaveok.name);
  834.           strcpy(ev.data.msg.data.datasaveok.name,buf);
  835.           ev.data.msg.hdr.size = (strlen(ev.data.msg.data.datasaveok.name)|3)+1+44;
  836.           ev.data.msg.hdr.your_ref = ev.data.msg.hdr.my_ref;
  837.           ev.data.msg.hdr.action = wimp_MDATASAVEOK;
  838.           wimp_sendmessage(wimp_ESEND,&ev.data.msg,ev.data.msg.hdr.task);
  839.           maydataload = 1;
  840.           goto pol;
  841.         case wimp_MDATASAVEOK:
  842.           if (strcmp(ev.data.msg.data.datasaveok.name, "<Wimp$Scrap>") == 0) goto pol;
  843.           sprintf(buf, "ColonSemi %s\n", ev.data.msg.data.datasaveok.name);
  844.           r.r[0] = (int) buf;
  845.           _kernel_swi(OS_CLI, &r, &r );
  846.           strcpy(buf, "Do Filer_OpenDir Mem#|<ColonSemi>:$");
  847.           r.r[0] = (int) buf;
  848.           _kernel_swi(OS_CLI, &r, &r );
  849.           wind_setstring(wind_create, 2, ev.data.msg.data.datasaveok.name);
  850.           ev.data.msg.hdr.your_ref = ev.data.msg.hdr.my_ref;
  851.           ev.data.msg.hdr.action = wimp_MDATALOAD;
  852.           wimp_sendmessage(wimp_ESEND,&ev.data.msg,ev.data.msg.hdr.task);
  853.           goto pol;
  854.         case wimp_MDATALOAD:
  855.           if (maydataload)
  856.           {
  857.             /* Load from application */
  858.             ev.data.msg.hdr.your_ref = ev.data.msg.hdr.my_ref;
  859.             ev.data.msg.hdr.action = wimp_MDATALOADOK;
  860.             wimp_sendmessage(wimp_ESEND,&ev.data.msg,ev.data.msg.hdr.task);
  861.             maydataload = 0;
  862.           } else
  863.           {
  864.             int handle = wimp_newtask("Filer_Action");
  865.             int tail;
  866.             int x, y, rename;
  867.             char dir[256];
  868.             char leaf[32];
  869.             char *name = ev.data.msg.data.dataload.name;
  870.  
  871.             /* Load from file/directory
  872.                Setup some cunning filer_action move/copy action with messages */
  873.  
  874.             if (handle == 0) goto pol;
  875.             /* Send ack to application (filer) */
  876.             ev.data.msg.hdr.your_ref = ev.data.msg.hdr.my_ref;
  877.             ev.data.msg.hdr.action = wimp_MDATALOADOK;
  878.             wimp_sendmessage(wimp_ESEND,&ev.data.msg,ev.data.msg.hdr.task);
  879.  
  880.             x = 0x80;                   /* Test for SHIFT key == move files */
  881.             os_byte(121, &x, &y);
  882.             rename = x ? 1 : 0; 
  883.  
  884.             tail = strlen(name);
  885.             while (tail > 0 && name[tail-1] != '.' && name[tail-1] != ':') tail--;
  886.             strncpy(dir, name, tail-1);
  887.             dir[tail-1] = '\0';
  888.             strcpy(leaf, &name[tail]);
  889.  
  890.             ev.data.msg.hdr.your_ref = 0;
  891.             ev.data.msg.hdr.action = wimp_MFilerSelectionDirectory;
  892.             strcpy((char *) &ev.data.msg.data.words[0], dir);
  893.             wimp_sendmessage(wimp_ESEND,&ev.data.msg,handle);
  894.  
  895.             ev.data.msg.hdr.your_ref = 0;
  896.             ev.data.msg.hdr.action = wimp_MFilerAddSelection;
  897.             strcpy((char *) &ev.data.msg.data.words[0], leaf);
  898.             wimp_sendmessage(wimp_ESEND,&ev.data.msg,handle);
  899.  
  900.             ev.data.msg.data.words[0] = rename;
  901.             ev.data.msg.data.words[1] = 1;
  902.             sprintf((char *) &ev.data.msg.data.words[2], "%s::%s.$\0", FS, DISK);
  903.             ev.data.msg.hdr.your_ref = 0;
  904.             ev.data.msg.hdr.action = wimp_MFilerAction;
  905.             wimp_sendmessage(wimp_ESEND,&ev.data.msg,handle);
  906.           }
  907.           continue;
  908.         case wimp_MDATALOADOK:
  909.           /* Redundant stage - we don't care if receiver died or not */
  910.           continue;
  911.         case wimp_SAVEDESK:     /* RISC OS 3.xx 'Desktop save' feature */
  912.           {
  913.             int fh = ev.data.msg.data.savedesk.filehandle;
  914.             char command[256];
  915.             char buf[256];
  916.             char *path;
  917.             int nsprites;
  918.  
  919.             r.r[0] = 8;
  920.             err=(os_error *)_kernel_swi(OS_SpriteOp, &r, &r );
  921.             nsprites = r.r[3];
  922.             if ((err) || (nsprites < 1) || (r.r[2] < 1)) nsprites = 0;
  923.             r.r[0] = (int) "Memphis$Dir";
  924.             r.r[1] = (int) &buf;
  925.             r.r[2] = 255;
  926.             r.r[3] = 0; r.r[4] = 0;
  927.             _kernel_swi( OS_ReadVarVal, &r, &r );
  928.             buf[(r.r[2])] = '\0';
  929.  
  930.             path = (char *) r.r[1];
  931.             if (path == NULL) continue;
  932.             if (nsprites > 0)
  933.             {
  934.               wimp_starttask("SSave <Memphis$Dir>.SavedSpr");
  935.               sprintf(command, "SLoad %s.SavedSpr\n", path);
  936.               rofprint(fh, command);
  937.             }
  938.             sprintf(command, "/%s\n", path);
  939.             rofprint(fh, command);
  940.           }
  941.           continue;
  942.  
  943.         default:
  944.           continue;
  945.       }
  946.       break;
  947.  
  948.     default:
  949.       continue;
  950.     }
  951.     break;
  952.   }
  953.   return 0;
  954.  
  955. error:
  956.   wimp_reporterror(err,0, FilerName);
  957.   return (int)err;
  958. }
  959.